package io.renren.modules.doc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.doc.dao.DenseRagDao;
import io.renren.modules.doc.entity.DenseRagEntity;
import io.renren.modules.doc.service.DenseRagService;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 向量检索服务实现
 */
@Service("denseRagService")
public class DenseRagServiceImpl extends ServiceImpl<DenseRagDao, DenseRagEntity> implements DenseRagService {

    // 向量维度
    private static final int VECTOR_DIM = 384;
    
    // 随机数生成器，用于生成模拟向量
    private final Random random = new Random();

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String title = (String)params.get("title");

        IPage<DenseRagEntity> page = this.page(
                new Query<DenseRagEntity>().getPage(params),
                new QueryWrapper<DenseRagEntity>()
                        .like(StringUtils.isNotBlank(title), "title", title)
        );

        return new PageUtils(page);
    }
    
    @Override
    public DenseRagEntity getDetail(Long id) {
        return this.getById(id);
    }
    
    @Override
    public void deleteBatch(Long[] ids) {
        this.removeByIds(Arrays.asList(ids));
    }

    @Override
    public List<DenseRagEntity> searchSimilar(String query, int limit) {
        byte[] embeddings = generateEmbeddings(query);
        return baseMapper.searchSimilar(embeddings, limit);
    }

    @Override
    public byte[] generateEmbeddings(String text) {
        if (text == null || text.isEmpty()) {
            // 返回空向量
            return new byte[VECTOR_DIM];
        }
        
        // 在实际应用中，这里应该调用向量嵌入模型API
        // 例如OpenAI、HuggingFace等提供的嵌入模型
        // 以下是模拟实现，生成-1到1范围内的随机浮点数，然后转换为byte
        
        byte[] result = new byte[VECTOR_DIM];
        
        // 使用文本的哈希值作为随机数种子，确保相同文本生成相同的向量
        random.setSeed(text.hashCode());
        
        for (int i = 0; i < VECTOR_DIM; i++) {
            // 生成-1.0到1.0之间的随机浮点数，然后映射到byte范围(-127到127)
            float randomValue = (random.nextFloat() * 2.0f) - 1.0f;
            result[i] = (byte)(randomValue * 127.0f);
        }
        
        // 归一化向量，确保L2范数为1
        normalizeVector(result);
        
        return result;
    }
    
    /**
     * 归一化向量，使其L2范数为1
     * 这对于向量相似度计算很重要
     */
    private void normalizeVector(byte[] vector) {
        // 计算平方和
        double sumOfSquares = 0.0;
        for (byte b : vector) {
            float value = b / 127.0f;
            sumOfSquares += value * value;
        }
        
        // 计算L2范数
        double magnitude = Math.sqrt(sumOfSquares);
        
        // 如果向量全为0，无需归一化
        if (magnitude < 1e-6) {
            return;
        }
        
        // 归一化向量
        for (int i = 0; i < vector.length; i++) {
            float value = vector[i] / 127.0f;
            value = (float)(value / magnitude);
            vector[i] = (byte)(value * 127.0f);
        }
    }
}
